#ifndef JPM_DEV_STATUS_H
#define JPM_DEV_STATUS_H

#include <stdint.h>
#include <stdbool.h>

//#define _DISPLAY_POWER_ALL_TIME_

//#define _TEST_FLAG_
#ifdef  _TEST_FLAG_
//#define   _VIRTRUAL_DISCHARGE_
//#define  _VIRTRUAL_CHARGE_
#endif

//#define _NO_SLEEP_

#define SOFTWARE_VERSION_STRING  "1.0.1.8"
#define HARDWARE_VERSION_STRING  "1.0"


#define GET_ADC_STATUS_DELAY            10
#define GET_ADC_STATUS_LOOP_DELAY       100

#define WORK_CLK               84000000
#define IDLE_CLK               4000000

#define SWITCH_HUB      1
#define SWITCH_JPM      0

#define HUB_VBUS_ON        0
#define HUB_VBUS_OFF       1

#define SWITCH_CHARGE           0
#define SWITCH_NO_CHARGE        1

#define PUSH_BUTTON_PRESS       0
#define PUSH_BUTTON_NO_PRESS    1

#define BTR_LEVEL_DISPLAY_FLAG  GPBR0
#define LED_STATE_FLAG          GPBR1        
#define LED_CHARGE_START_FLAG   GPBR2
#define PC_FLAG                 GPBR3
#define BTR_LEVEL_FLAG          GPBR4
#define BTR_STATE_FLAG          GPBR5
#define POWER_ON_FLAG           GPBR6
#define PC_VERIFY_FLAG          GPBR7

#define  SD_BLK_OFFSET_ADDR          20480   //10M reserved 
#define  PC_CONNECT_FLAG_BLK_ADDR    0
#define  IPHONE_ID_BLK_ADDR          1
#define  PWD_NEED_BLK_ADDR           2
#define  PWD_STORE_BLK_ADDR_A        3
#define  PWD_STORE_BLK_ADDR_B        4
#define  EMAIL_FLAG_BLK_ADDR         5
#define  EMAIL_STORE_BLK_ADDR_A      6
#define  EMAIL_STORE_BLK_ADDR_B      7
//#define  PWD_SET_BLK_ADDR            7
#define  PART_NUMBER_ADDR            16

typedef enum {
  JPM_POWER_ON = 0,
  JPM_CONNECT_PC = 1,
  JPM_NORMAL_MSC,
  JPM_CONNECT_IPHONE,
  JPM_GREEN_MODE,
  JPM_RED_MODE,
  JPM_CHARGE_MODE,
  JPM_SLEEP,
  JPM_DISCHARGE_IDLE,
  JPM_CHARGE_IDLE,
  JPM_DISCHARGE_PROTECT,
  JPM_CHARGE_PROTECT,
  JPM_WARNING,
  JPM_LOW_POWER_CHARGE,
  JPM_RESET,
#ifdef SUPPORT_OTG
  JPM_CONNECT_OTG,
#endif
}jpm_status_machine_t;

typedef struct{
  uint8_t last;
  uint8_t current;
}jpm_status_t;

typedef enum{
  HUB_DISCNCT = 0,
  HUB_CNCT = 1,
}usb_connect_status_t;

typedef enum{
  SWT_ON = 0,
  SWT_OFF = 1, 
  SWT_UNKNOWN = 2,
}switch_status_t;

typedef enum{
  P_SRC_NONE = 0,
  P_SRC_0P5A = 1, 
  P_SRC_PC, 
  P_SRC_EX_1A,
  P_SRC_EX_1P5A,
  P_SRC_EX_2P1A,  
  P_SRC_PC_PRE,
}ex_power_source_type_t;

typedef enum{
  BTR_NORMAL = 0,
  BTR_LOW = 1,
  BTR_PROTECT = 2,
}btr_status_t;

typedef enum{
  NO_CHARGE_CUR = 0,
  CHARGE_CUR_NORMAL = 1,
}ele_cur_status_t;

typedef enum{
  ALL_OFF = 0,
  LED_LEVEL_1 = 1,
  LED_LEVEL_2,
  LED_LEVEL_3,
  LED_LEVEL_4,
  ALL_ON,
}led_status_t;

typedef enum{
  BTR_EMPTY = 0,        //no power, no LED indicator
  LESS_THAN_5 = 1,      //0%~5%, hysterisis to turn high power mode
  LESS_THAN_12,     //5%~12%, no charging iPhone when disconnected to external power
  LESS_THAN_25,     //12%~25%, 1LED indicator
  LESS_THAN_50,     //25%~50%, 2LED indicator
  LESS_THAN_75,     //50%~75%, 3LED indicator
  LESS_THAN_100,    //75%~100%, 4LED indicator
  BTR_FULL,
}battery_level_t;

typedef enum{
  PMU_STATE_RESET = 0,
  PMU_STATE_START_CHARGE,
  PMU_STATE_MONITOR_CHARGING,
  PMU_STATE_STOP_CHARGE,
  PMU_STATE_START_DISCHARGE,
  PMU_STATE_MONITOR_DISCHARGING,
  PMU_STATE_STOP_DISCHARGE,    
  PMU_STATE_SLEEP
}pmu_state_t;

typedef enum{
  USB_NONE = 0,
  USB_HOST,
  USB_ROLE_SWITCH,
  USB_DEVICE,
  USB_RESET,
  USB_ADDRESSED,
  USB_CONFIGED,  
}usb_switch_status_t;

typedef enum{
  MCU_INIT = 0,
  MCU_WORK = 1,
  MCU_LOW_POWER,
}mcu_work_status_t;

typedef struct{
  uint8_t usb_cnct_status;
  uint8_t switch_status;
  uint8_t ex_power_type; 
  uint8_t battery_status; 
  uint8_t ele_cur_status;
  uint8_t battery_power;
  uint8_t led_status;
  uint8_t pmu_status;
  uint8_t usb_role;
  uint8_t mcu_status;
}ex_status_t;

#define ITERM_MASK 0XF0
#define ITERM_128 0X00
#define ITERM_256 0X01

#define REG0_ADDR 0X00
#define REG1_ADDR 0X01
#define REG2_ADDR 0X02
#define REG3_ADDR 0X03
#define REG4_ADDR 0X04
#define REG5_ADDR 0X05
#define REG6_ADDR 0X06
#define REG7_ADDR 0X07
#define REG8_ADDR 0X08
#define REG9_ADDR 0X09

enum reg_idx{
    REG0=0,
    REG1=1,
    REG2=2,
    REG3=3,
    REG4=4,
    REG5=5,
    REG6=6,
    REG7=7,
    REG8=8,
    REG9=9,
    REG_MAX   
};

#define BOST_CHIP_ADDR           (0x6B)      
#define BOST_REG_LENGTH          1
#define TWI_PMU                  TWI0

#define VBUS_STAT_MASK 0XC0
#define VBUS_STAT_UNKNOWN 0X00
#define VBUS_STAT_USBHOST 0X40
#define VBUS_STAT_ADAPTER 0X80
#define VBUS_STAT_OTG 0XC0
#define DLY_CHARGER_HANDLE  10
#define VBUS_STAT_MASK 0XC0
#define VBUS_STAT_UNKNOWN 0X00
#define VBUS_STAT_USBHOST 0X40
#define VBUS_STAT_ADAPTER 0X80
#define VBUS_STAT_OTG 0XC0

#define IINLIM_HIZ_ENTER 0X80
#define IINLIM_HIZ_EXIT 0X00
#define IINLIM_100MA 0X00
#define IINLIM_500MA 0X02
#define IINLIM_900MA 0X03
#define IINLIM_1200MA 0X04
#define IINLIM_1500MA 0X05
#define IINLIM_2000MA 0X06

#define DISABLE_WD 0X8C
#define BATFET_OFF 0X63
#define BATFET_ON 0X43
#define OTG_ON 0X20
#define OTG_ON_MASK 0X20
#define OTG_OFF 0X00

#define CHRG_DONE 0X30
#define CHRG_STAT_MASK 0X30

#define CHRG_FAULT_MASK 0X3F
#define CHRG_NO_FAULT 0X00
#define DISCHRG_FAULT_MASK 0X47
#define DISCHRG_NO_FAULT 0X00

#define MUI_ID_1_0	0x2AAA	//1V
#define MUI_ID_1_4	0x3BBB	//1.4V
#define MUI_ID_2_0_MIN	0x4CCC	//1.8V
#define MUI_ID_2_0_MAX	0x5DDD	//2.2V
#define MUI_ID_2_7_MIN	0x6AAA	//2.5V
#define MUI_ID_2_7_MAX	0x7BBB	//2.9V

#define VINDPM_MASK 0X78
//#define VINDPM_468V 0X50
#define VINDPM_476V 0X58

#define MUI_LOAD_CURR_LVL1              0x0976	//0.125A
#define MUI_LOAD_CURR_LVL2              0x1C62	//0.375A
#define MUI_LOAD_CURR_LVL3              0x2F4E	//0.625A
#define MUI_LOAD_CURR_LVL4              0x423A	//0.875A
#define MUI_OCP_LIMIT	                    0x5AD4	//1.2A
//#define BYPASS_OCP_LIMIT	             0x7F80	//(4095-15)*8
#define BYPASS_OCP_LIMIT	             0x5AD4	//1.2A
#define MUI_BAT_VOLT_LOW_LIMIT      0x5D4D	//3.2V
#define BAT_VOLTAGE_335V                   0x61AD	//3.35V
#define MIN_LOAD_CURR	                     0x03C8	//50mA
#define CURR_1A	                                    0x4BB0	//1.0A
#define CURR_0P9A	                            0x441F	//0.9A
#define CURR_0P5A	                            0x25D8	//0.5A

#define OVP_THR	                            0x2AAA	//6V
#define OVP_RELEASE	                            0x26C1	//5.45

extern jpm_status_t g_jpm_status;
extern ex_status_t ex_status;
extern uint32_t g_power_led_idx;
//extern uint8_t g_check;
//extern uint8_t g_re_pc_wait;
//extern uint8_t g_charge_led;
//extern uint8_t g_nocharge_led;
//extern uint8_t g_start_sleep;
//extern uint8_t g_start_delay;
//extern bool b_usb_switch;
extern bool b_iap2_fail;
extern bool b_led_display;
extern bool b_charge_configued;
extern bool b_button_pressed_before_sleep;
//extern uint8_t charge_led_init;
extern bool sysclk_run_fastest;
extern bool b_iOS6;


void charge_led_proc(void);
void turn_on_led_from_power(void);
void turn_all_led(bool b_on);
void led_flick(void);

void status_init(void);

void set_usb_switch(uint8_t s);
void reset_system(void);
void enter_sleep_mode(bool b_tri_awake);
void enter_light_sleep_mode(void);
void enter_stand_by_mode(void);
void enter_work_mode(void);

uint8_t power_detect(void);
uint8_t get_hub_vbusin_state(void);
bool Is_charge(void);
uint8_t get_charge_state(void);
bool Is_button_pressed(void);

void ocp_chk (uint16_t ocp_limit);
void ovp_chk (void);
void bq_dvc_all_reg_rd(void);
uint8_t get_bat_remain_capacity (void);
void update_power_state(void);
void start_charge(void);
void start_low_power_charge(void);
uint16_t monitor_charging(void);
void stop_charge(void);
void start_discharge(void);
uint16_t monitor_discharging(void);
void stop_discharging(void);
void pmu_sleep(void);
void bq_dvc_wr(uint8_t addr, uint8_t dat);
void bq_dvc_rd(uint8_t addr, uint8_t* dat);
void update_iterm (void);
void init_work_mode(void);
//void pmu_exit_sleep(void);

void start_wdt(void);
#define feed_dog() wdt_restart(WDT)

void restore_battery_power(bool b_display, bool b_charge);
bool load_battery_power(void);
#define clear_battery_level_display() gpbr_write(BTR_LEVEL_DISPLAY_FLAG, 0)

#define Is_charge_start()                   ((bool)((uint8_t)(gpbr_read(LED_CHARGE_START_FLAG))))
#define clear_charge_start_flag()           gpbr_write(LED_CHARGE_START_FLAG, 0)
#define restore_pc_flag()                   gpbr_write(PC_FLAG, 1)
#define Is_pc_flag()                        ((bool)((uint8_t)(gpbr_read(PC_FLAG))))
#define clear_pc_flag()                     gpbr_write(PC_FLAG, 0)

#define make_power_on_flag()                gpbr_write(POWER_ON_FLAG, 1)
#define Is_power_on()                       ((bool)((uint8_t)(gpbr_read(POWER_ON_FLAG))))  

#define make_led_charge_start_flag()        gpbr_write(LED_CHARGE_START_FLAG, 1)

#define Is_pc_verified()                    ((bool)((uint8_t)(gpbr_read(PC_VERIFY_FLAG)))) 
#define restor_pc_verified_flag()           gpbr_write(PC_VERIFY_FLAG, 1)
#define clear_pc_verified_flag()            gpbr_write(PC_VERIFY_FLAG, 0)

static inline void update_jpm_status(uint8_t status)
{
    g_jpm_status.last = g_jpm_status.current;
    g_jpm_status.current = status;
}

void get_part_number(void);
void set_part_number(uint8_t capa_flag, uint8_t color_flag);
bool Is_vbusin_changed(void);
bool Is_email_set(void);
bool Is_temp_pwd(void);
bool verify_pwd(uint8_t *pwd);
void store_pwd(uint8_t *pwd, bool b_temp);
void get_pwd_need_info(void);
void modify_sn_code(void);
void modify_email_addr(uint8_t *addr);
void clear_pwd_need(void);
void erase_all_protection(void);
void get_pwd_email(uint8_t *data_buffer, uint8_t *seed);
void get_email_addr(uint8_t *email_addr);

extern bool b_need_to_verify;
extern bool b_verified;

extern bool b_set_pwd_success;
extern bool b_modify_pwd_success;
extern bool b_set_email_success;

extern uint8_t g_pass_word[20];
extern uint8_t g_modify_code[20];
extern uint8_t g_email_addr[68];

extern uint8_t   sd_card_sn[16];
extern uint8_t   g_part_number[32];

void init_modify_code(void);
#endif
